/*******************************************************************************
 * Copyright 2011-2012 Dik Grapendaal
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package sh.grapendaal.tsuushin.module;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import sh.grapendaal.tsuushin.core.Context;
import sh.grapendaal.tsuushin.message.IncomingMessage;
import sh.grapendaal.tsuushin.message.MessageType;

public interface ModuleContainer {
	/**
	 * Returns the main class of this module. This is the class that has been
	 * annotated with @Module.
	 * 
	 * @return The main class of the module.
	 */
	Class<?> getMainClass();

	/**
	 * Sets the main class of the module. This class will be used as the entry
	 * point from the host application to the module. The annotations which
	 * define callbacks are only processed on this class.
	 * 
	 * @param mainClass
	 *            The main class of the module.
	 */
	void setMainClass(Class<?> mainClass);

	/**
	 * Returns the method on which the @Start annotation was defined.
	 * 
	 * @return The method to be invoked when the module gets started.
	 */
	Method getStartMethod();

	/**
	 * Sets the method to be invoked when the module gets started.
	 * 
	 * @param startMethod
	 *            The method to invoke.
	 */
	void setStartMethod(Method startMethod);

	/**
	 * Returns the method on which the @Stop annotation was defined.
	 * 
	 * @return The method to be invoked when the module gets stopped.
	 */
	Method getStopMethod();

	/**
	 * Sets the method to be invoked when the module gets stopped.
	 * 
	 * @param stopMethod
	 *            The method to invoke.
	 */
	void setStopMethod(Method stopMethod);

	/**
	 * Instantiates the main class, injects the requested services and calls the
	 * start method if one has been defined.
	 * 
	 * @throws RuntimeException
	 *             If the instantiation failed somehow.
	 */
	void instantiate();

	/**
	 * Invokes the stop method if there is one, and shuts down the module
	 * cleanly.
	 */
	void destroy();

	/**
	 * Registers a permission as being defined by this module. This uses the
	 * proxy of this module for the Permission Service. If there is no proxy
	 * created yet, it will be created and used for later injections.
	 * 
	 * @param permission
	 *            The permission to register.
	 */
	void registerPermission(String permission);

	/**
	 * Registers the given field as a field which needs to be injected with a
	 * reference to one of the host application's services.
	 * 
	 * @param field
	 *            The field to wire.
	 */
	void addServiceWire(Field field);

	/**
	 * Registers the given method to be invoked when a message of the given
	 * message type is received.
	 * 
	 * @param method
	 *            The method to invoke.
	 * @param messageType
	 *            The message type applicable for this method.
	 */
	void addCallback(Method method, MessageType messageType);

	/**
	 * Invokes the methods that have been registered with the message type of
	 * the given incoming message. The context and the message will be passed to
	 * any method that matches, if it needs them.
	 * 
	 * @param context
	 *            The current context, meaning the bot and network.
	 * @param message
	 *            The parsed message that was received.
	 */
	void dispatchCallbacks(Context context, IncomingMessage message);

}
